import {
  VuexModule,
  Module,
  Mutation,
  Action,
  getModule
} from 'vuex-module-decorators'
import { RouteConfig } from 'vue-router'
import { asyncRoutes, constantRoutes } from '@/router'
import store from '@/store'
import Layout from '@/layout/index.vue'
import page404 from '@/views/error-page/404.vue'
import pageMultiRoute from '@/layout/components/multiRoute/index.vue'
import { isExternal } from '@/utils/validate'
import { config } from '@/microAppConfig'
const multiplexComp = '__reuse__'
// 不依赖于layout sidebar组件
export const DONOTRENDERMENUROUTES = ['/404', '/guide']
// 可复用组件
/**
 *找到当前路由对应的id
 *
 * @param {RouteConfig[]} arr
 * @param {string} path
 * @returns
 */
const findCurrentId = (arr: RouteConfig[], path: string) => {
  let currentId = ''
  for (let i = 0; i < arr.length; i++) {
    if (currentId) return currentId
    if (arr[i].path === path) {
      currentId = arr[i].meta.id
      break
    } else {
      if (arr[i].children && (<RouteConfig[]>arr[i].children).length > 0) {
        currentId = findCurrentId(<RouteConfig[]>arr[i].children, path)
      }
    }
  }
  return currentId
}
export function findRouteById(arr: RouteConfig[], id: string) {
  let tempRoute: any = ''
  for (let i = 0; i < arr.length; i++) {
    if (tempRoute) return tempRoute
    if (arr[i].meta.id === id) {
      tempRoute = arr[i]
      break
    } else {
      if (arr[i].children && (<RouteConfig[]>arr[i].children).length > 0) {
        tempRoute = findRouteById(<RouteConfig[]>arr[i].children, id)
      }
    }
  }
  return tempRoute
}
/**
 *递归找寻菜单树（一条），从一级到叶子菜单，判断当前systemId
 页面刷新初始化加载，和点击tag时用到
 *
 * @param {RouteConfig[]} arr
 * @param {string} path
 * @returns
 */
export function findSystemId(arr: RouteConfig[], path: string): any {
  // 先找到当前路由自身的id
  let currentId = findCurrentId(arr, path)
  // 把所有路径装进一个平行数组而不是树状结构
  let tempWholeTree: RouteConfig[] = []
  let forFnArr = function(arr: RouteConfig[]) {
    arr.forEach(item => {
      tempWholeTree.push(item)
      if (item.children && item.children.length > 0) {
        forFnArr(item.children)
      }
    })
  }
  forFnArr(arr)
  let familyTree: RouteConfig[] = []
  // 根据最后一个id找到整个家族family
  let forFnFamily = function(arr: RouteConfig[], id: string) {
    if (id === undefined) {
      return false
    }
    for (let i = 0; i < arr.length; i++) {
      let item = arr[i]
      if (item.meta.id === id) {
        familyTree.push(item)
        forFnFamily(arr, item.meta.pid)
      }
    }
  }
  forFnFamily(tempWholeTree, currentId)
  // 最终找到一级系统菜单，pid===1的route
  let tempItem = familyTree.find(item => {
    return item.meta.pid === '1'
  })
  if (tempItem) {
    return tempItem.meta.id
  } else {
    // 如果没找到，一定是以 ‘/’开头的系统
    return findSystemId(arr, '/')
  }
}

/**
 * 获取叶子菜单path，页面默认跳转 / redirect到叶子路径
 * @param router：一个菜单树，永远取第0个children
 */
const getVueRouterConfigPath = (router: any) => {
  // 最底层节点称之为叶子节点
  let leafNodePath: string
  if ((<String>router.route).length > 0 && (<[]>router.children).length === 0) {
    leafNodePath = router.route
  } else {
    leafNodePath = getVueRouterConfigPath(router.children[0])
  }
  return leafNodePath
}
// 默认/index跳转手动把第一个二级菜单得第一个子菜单（或者子菜单钟得子菜单）配置为第一个叶子菜单
const setFirstMenuIndex = (menu: any[]) => {
  // 获取原有path，用于详情附着父级菜单高亮
  let originPath = ''
  // 最底层节点称之为叶子节点
  let tempFirstRoute = {
    path: '/index',
    redirect: '',
    component: Layout,
    meta: {
      title: '...',
      hidden: true
    }
  }
  menu.forEach((item, index) => {
    if (index === 0 && item.children && item.children.length > 0) {
      setFirstMenuIndex(item.children)
    } else {
      if (index === 0) {
        tempFirstRoute.redirect = item.path
        originPath = item.path
        menu.push(tempFirstRoute)
      }
    }
  })
  // return originPath
}
const getFirstLevelSecondLevelNodes = (routerMap: any[]) => {
  let firstLevel: any[] = []
  let secondLevel: any[] = []
  // 一级系统
  routerMap.forEach(route => {
    if (route.parent_id === 1) {
      firstLevel.push(route.id)
    }
  })
  // 2级系统
  firstLevel.forEach(id => {
    routerMap.forEach(route => {
      ;(<any[]>(route as any).children).forEach((sec: any) => {
        if (sec.parent_id === id) {
          secondLevel.push(sec.id)
        }
      })
    })
  })

  return {
    firstLevel: firstLevel,
    secondLevel: secondLevel
  }
}
/**
 * 根据远程获取的用户菜单，递归生成路由(系统所有路由，sidebar路由)
 */
const filterAsyncRouter = (
  routerMap: any[],
  firstLevelId: any[],
  secondLevelId: any[]
) => {
  let accessedRoutes: RouteConfig[] = []

  routerMap.forEach((route, index) => {
    let tempRouteConfig = <RouteConfig>{}
    tempRouteConfig.children = filterAsyncRouter(
      route.children,
      firstLevelId,
      secondLevelId
    )
    tempRouteConfig.meta = {
      icon: route.icon ? route.icon : 'component',
      title:
        tempRouteConfig.children.length === 0 &&
        secondLevelId.indexOf(route.id) > -1
          ? ''
          : route.name,
      id: route.id + '',
      pid: route.parent_id + '',
      noCache: route.route.includes('dashboard'),
      showScreenFull: route.route.includes('dashboard'),
      type: undefined
    }
    if (!route.children) {
      route.children = []
    }

    // 二级菜单没有子路由,必须依赖layout，所以其本身component一定是Layout
    if (
      tempRouteConfig.children.length === 0 &&
      secondLevelId.indexOf(route.id) > -1
    ) {
      // 页面一登录进来默认首页设置，子路径跳转到.index
      tempRouteConfig.path = index === 0 ? '/' : route.route
      tempRouteConfig.component = Layout
      tempRouteConfig.redirect = '/index'
      // 控制导航面包屑只显示单独一条,虚假下拉列表
      tempRouteConfig.meta.fakeFirstMenu = true
      var childIndexComponent = <RouteConfig>{}
      childIndexComponent.name = route.id + ''
      childIndexComponent.meta = {
        icon: route.icon ? route.icon : 'component',
        title: route.name,
        id: route.id + '',
        pid: route.parent_id + '',
        noCache: route.route.includes('dashboard'),
        showScreenFull: route.route.includes('dashboard')
      }
      try {
        // 如果是子应用
        if (config.some(it => route.route.startsWith(it.activeRule))) {
          childIndexComponent.path = route.route
        } else if (route.route.includes(multiplexComp)) {
          // 多组件复用参考https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html
          childIndexComponent.path = route.route + '/index' + `/${route.id}`
        } else {
          childIndexComponent.path = route.route + '/index'
        }
      } catch (error) {
        console.log('菜单加载异常' + error)
        // 菜单栏加载失败直接加载404
        childIndexComponent.component = page404
      }
      // 检查是否外部链接
      if (isExternal(route.route)) {
        childIndexComponent.path = route.route
      }
      tempRouteConfig.children.push(childIndexComponent)
    } else {
      tempRouteConfig.meta.alwaysShow = true
      tempRouteConfig.name = route.id + ''
      // 二级菜单有子路由以及子路由下还有子路由,只有二级菜单才会依赖于layout
      if (secondLevelId.indexOf(route.id) > -1) {
        tempRouteConfig.path = index === 0 ? '/' : route.route
        tempRouteConfig.redirect = getVueRouterConfigPath(route.children[0])
        tempRouteConfig.component = Layout
      } else {
        tempRouteConfig.path = route.route
        // 多级菜单得区别是pageMultiRoute的使用
        if ((<String>route.route).length > 0 && route.children.length === 0) {
          tempRouteConfig.children = undefined
          // 只展示一层，不可下拉
          tempRouteConfig.meta.alwaysShow = false
          // 多组件复用参考https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html
          try {
            // 如果是子应用
            if (config.some(it => route.route.startsWith(it.activeRule))) {
              if (route.route.includes(multiplexComp)) {
                let tempSplitRoute = route.route.split('__reuse__')
                // 如果__reuse__后面还会加参数，则此参数代表该页面类型
                tempRouteConfig.path = route.route + `/${route.id}`
                tempRouteConfig.meta.type = tempSplitRoute[1].length
                  ? tempSplitRoute[1].substring(1)
                  : undefined
              }
              // 非子应用
            } else {
              // // tempRouteConfig.component = Layout
              // if (route.route.includes(multiplexComp)) {
              //   let tempSplitRoute = route.route.split('__reuse__')
              //   // 如果__reuse__后面还会加参数，则此参数代表该页面类型
              //   tempRouteConfig.path = route.route + `/${route.id}`
              //   tempRouteConfig.meta.type = tempSplitRoute[1].length
              //     ? tempSplitRoute[1].substring(1)
              //     : undefined
              //   tempRouteConfig.component = () =>
              //     import(
              //       '@/views' +
              //         tempSplitRoute[0].substr(
              //           0,
              //           tempSplitRoute[0].length - 1
              //         ) +
              //         '.vue'
              //     )
              // } else {
              // }
            }
          } catch (error) {
            console.log('菜单加载异常' + error)
            // 菜单栏加载失败直接加载404
            tempRouteConfig.component = page404
          }
        } else {
          // 注意，这里会有附着菜单，小心出现路由path重复，被覆盖掉，component为空，导致页面空白
          tempRouteConfig.component = pageMultiRoute
        }
      }
    }
    // 创建的菜单一定是各个系统，所以一定存在公共layout
    accessedRoutes.push(tempRouteConfig)
  })
  return accessedRoutes
}

export function toMatch(o: any, path: string) {
  if (o.path === path) {
    return [o]
  }
  if (o.children && o.children.length) {
    for (var idx = 0; idx < o.children.length; idx++) {
      var tm = toMatch(o.children[idx], path)
      if (tm) {
        const arr = [o]
        tm.forEach(it => {
          arr.push(it)
        })
        return arr
      }
    }
  }
}

export interface IPermissionState {
  // 系统可以加载的所有子路由，包含constantRoutes（login，404等公共路由），不包含系统路由本身
  routes: RouteConfig[]
  // 系统可以加载的所有子路由（除开login，404等公共路由）所有子路由，及系统下的二级子路由（包含三级，四级），不包含系统路由本身
  dynamicRoutes: RouteConfig[]
  // 接口请求--所有路由，系统一级路由，二级路由，包含系统本身
  systemRoutes: RouteConfig[]
  // 所有二级路由，用于第一次渲染加载
  sideBarRoutes: RouteConfig[]
  // 系统id
  systemId: any
  // 面包屑数组
  breadcrumb: any
  // 面包屑是否由子应用生成
  isBreadcrumbListenerByMicro: boolean
}

interface IGenerateRoutes {
  menuTree: any[]
  systemId?: string
}

interface IPath {
  path: string
  meta?: any
}

@Module({ dynamic: true, store, name: 'permission' })
class Permission extends VuexModule implements IPermissionState {
  public routes: RouteConfig[] = []
  public dynamicRoutes: RouteConfig[] = []
  public systemRoutes: RouteConfig[] = []
  public sideBarRoutes: RouteConfig[] = []
  public systemId = ''
  public breadcrumb = []
  public isBreadcrumbListenerByMicro = false

  @Mutation
  private SET_ROUTES(routes: RouteConfig[]) {
    //所有路由
    this.routes = constantRoutes.concat(routes)
    //二级菜单路由
    this.dynamicRoutes = asyncRoutes.concat(routes)
  }

  @Mutation
  private SET_SIDEBARROUTES(routes: RouteConfig[]) {
    //所有二级菜单路由
    this.sideBarRoutes = routes
  }
  @Mutation
  private SET_SYSTEMROUTES(routes: RouteConfig[]) {
    //系统菜单路由（所有，用于头部系统菜单显示）
    this.systemRoutes = routes
  }
  @Mutation
  private SET_SYSTEMID(id: any) {
    this.systemId = id
  }
  @Mutation
  private SET_BREADCRUMB(routes: any) {
    this.breadcrumb = routes
  }

  @Mutation
  public SET_BY_MICRO() {
    this.isBreadcrumbListenerByMicro = true
  }
  @Mutation
  public SET_BY_MAIN() {
    this.isBreadcrumbListenerByMicro = false
  }

  /**
   *获取路由，包含系统路由，二级路由
   *
   * @param {IGenerateRoutes} arg
   * @memberof Permission
   */
  @Action({ rawError: true })
  //设置动态各个系统子路由
  public GenerateRoutes(arg: IGenerateRoutes) {
    let firstLevelId = getFirstLevelSecondLevelNodes(arg.menuTree).firstLevel
    let secondLevelId = getFirstLevelSecondLevelNodes(arg.menuTree).secondLevel
    // 重设路由为空，直接return
    if (arg.menuTree.length === 0) {
      this.SET_ROUTES([])
      this.SET_SYSTEMROUTES([])
      this.SET_SYSTEMID('')
      return false
    }
    let tempAllRoutes: RouteConfig[] = []

    let systemRoutes = filterAsyncRouter(
      arg.menuTree,
      firstLevelId,
      secondLevelId
    )
    setFirstMenuIndex(systemRoutes)
    systemRoutes.forEach((item: RouteConfig) => {
      if (item.children && item.children.length > 0) {
        ;(<RouteConfig[]>item.children).forEach((it: RouteConfig) => {
          tempAllRoutes.push(it)
        })
      }
    })
    this.SET_ROUTES(tempAllRoutes)
    this.SET_SYSTEMROUTES(systemRoutes)
  }
  @Action({ rawError: true })
  public GenerateSidebarMenu(arg: IPath) {
    const { path, meta } = arg
    let matched: any = this.systemRoutes
      .map(it => {
        return toMatch(it, path)
      })
      .find(Boolean) || [this.systemRoutes[0]]
    if (meta) {
      matched = matched.concat([{ path: '', meta }])
    }
    console.log(this.systemRoutes, matched)
    this.SET_BREADCRUMB(matched)
    this.SET_SYSTEMID(matched[0].name)
    this.SET_SIDEBARROUTES(matched[0].children)
  }
}

export const PermissionModule = getModule(Permission)
